﻿/*
 * Stardust Software R&D Group Confidential
 * Project: Vesalius Image Annotation - Name as Salomay
 *
 * (C) Copyright Stardust Software R&D Group. 2013
 *
 * The source code for this program is not published or otherwise divested of 
 * its trade secrets
 */

/**
 ** Declare namespace of project
 **/
var Salomay = new Object();

/**
 * Salomay standard event class, use it to restrict the event structure for different third-part framework
 * @author - Cheng Li, Sep 07, 2013
 **/
Salomay.Event = Class.create();
Salomay.Event.prototype = {
	initialize: function(options){ 
		 this.event = options.event;
		 this.target = options.target;
	} 
}

/**
 * Interface of rendering engine class, all engines used by Salomay system should implement this interface
 * @author - Cheng Li, Sep 07, 2013
 **/
Salomay.EngineInterface = Class.create();
Salomay.EngineInterface.prototype = {
	/**
	 * Constructor
	 **/
	initialize: function(options){ 
		 this.observerManager = new ObserverManager();
		 this.options = options;
		 this._initialize(options);
	},
	
	/**
	 * Add given shape into canvas
	 * @param - options JSON
	 **/
	addShape: function(options) {
		this._addShape(options);
	},
	
	/**
	 * Remove given shape from canvas
	 * @param - options JSON
	 * @return - the deleted shape
	 **/
	removeShape: function(options) {
		return this._removeShape(options);
	},
	
	/**
	 * Render all shapes added into canvas and refresh the graphic cache
	 * @param - options JSON
	 **/
	renderAll: function(options){
		this._renderAll(options);
		this.notifyObserver("On_canvas_render", {sender:this});
	},
	
	/**
	 * Switch to free drawing mode to paint like pencil, spray
	 * @param - options JSON
	 **/
	enableDrawingMode: function(options){
		this._enableDrawingMode(options);
	},
	
	/**
	 * Disable free drawing mode
	 * @param - options JSON
	 **/
	disableDrawingMode: function(options){
		this._disableDrawingMode(options);
	},
	
	/**
	 * Is drawing mode
	 * @return see if the engine turns on drawing mode
	 **/
	
	isDrawingMode: function(){
		return this._isDrawingMode();
	},
	
	/**
	 * Get selected group (all selected objects) on canvas
	 * @note - This feature is turned off by default
	 * @param - options JSON
	 * @return - all selected objects
	 **/
	getSelectedObjects: function(options){
		return this._getSelectedObjects(options);
	},
	
	/**
	 * Set a object to selected
	 * @param - options JSON
	 **/
	setSelectedObject: function(options){
		return this._setSelectedObject(options);
	},
	
	/**
	 * Get single selected object on canvas
	 * @param - options JSON
	 * @return - selected object
	 **/
	getSelectedObject: function(options){
		return this._getSelectedObject(options);
	},
	
	/**
	 * Cancel selected status for all selected objects
	 * @param - options JSON
	 **/
	discardAllSelectedObjects: function(options){
		this._discardAllSelectedObjects(options);
	},
	
	/**
	 * Bind canvas to some event and specify the callback
	 * @param - options JSON
	 **/
	on: function(options) {
		this._on(options);
	},
	
	/**
	 * Get the engine object, can be third-part engine adapters and Salomay rendering engine
	 * @return Salomay engine or engine adapter
	 **/
	getEngine:function(){
		return this.engine;
	},
	
	/**
	 * Set attribute value by specific name. If the object doesn't have the attribute, create it and give it given value
	 * @param name - property name
	 * @param value - property value
	 **/
	setProperty: function(name, value){
		this._setProperty(name, value);
	},
	
	/**
	 * Get attribute value from object
	 * @param name - property name
	 * @return value of property
	 **/
	getProperty: function(name) {
		return this._getProperty(name);
	},
	
	/**
	 * Return the name of engine
	 * @return name of engine
	 **/
	getEngineType: function(){
		return this._getEngineType();
	},
	
	/**
	 * Convert engine object to JSON
	 * @return JSON data of object
	 **/
	toJSON: function(){
		return this._toJSON();
	},
	
	/**
	 * Load data from JSON into engine
	 * @options JSON options
	 **/
	loadFromJSON: function(options) {
		this._loadFromJSON(options);
	},
	
	/**
	 * Get a list of shapes paint on current engine
	 * @return Salomay shape object list
	 **/
	getAllObjects: function(){
		return this._getAllObjects();
	},
	
	/**
	 * Set background image for engine
	 * @param JSON options contain image information
	 **/
	setBackgroundImage: function(options) {
		return this._setBackgroundImage(options);
	},
	
	/**
	 * Get shape object from engine with specific id
	 * @param id id of shape object
	 * @return shape object
	 **/
	getShapeById: function(id) {
		var shapes = this.getAllObjects();
		var returnVal = null;
		for (var i = 0; i < shapes.length; i++) {
			if (shapes[i].getId() != id) continue;
			returnVal = shapes[i];
			break;
		}
		return returnVal;
	},
	
	/**
	 * Find target from event
	 * @param event Salomay event object
	 * @return Salomay shape object
	 **/
	findTarget: function(event) {
		return this._findTarget(event);
	},
	
	/**
	 * Set brush options for canvas
	 * @param options brush options
	 **/
	setBrush: function(options) {
		this._setBrush(options);
	},
	
	/**
     * Add event lisenter for the instance
	 * @param event_name the name of observing event
	 * @param evecuter the this pointer for who call the method
	 * @param method event handler
     **/
    addObserver:function(event_name,executer,method){
	    var observer = new Observer(executer,method);
	    this.observerManager.AddObserver(event_name,observer);
    },
	  
    /**
     * Stop observe event
	 * @param event_name the name of observing event
	 * @param evecuter the this pointer for who call the method
	 * @param method event handler
     **/
    stopObserving:function(event_name,executer,method){
        var observer = new Observer(executer,method);
        this.observerManager.StopObserving(event_name,observer);
    },
  
    /**
     * Trigger event by giving event name
	 * @param event_name the name of observing event
	 * @param context context obect contains runtime variables
     **/
    notifyObserver:function(event_name,context){
        this.observerManager.NotifyAllObservers(event_name,context);
    }
}

/**
 * Interface of shapes
 * @author - Cheng Li, Sep 07, 2013
 **/
Salomay.ShapeInterface = Class.create();
Salomay.ShapeInterface.prototype = {
	/**
	 * Constructor
	 **/
	initialize: function(options){ 
		 this.observerManager = new ObserverManager();
		 this.options = options;
		 this._initialize(options);
		 this.bindEvents();
		 this.getShapeType();
	},
	
	/**
	 * Get id of shape object
	 * @return id of shape object
	 **/
	getId: function(){
		return this.getProperty("id");
	},
	
	/**
	 * Set id of shape object
	 * @id id of shape object
	 **/
	setId: function(id){
		return this.setProperty("id", id);
	},
	
	/**
	 * Render shape (itself) to canvas
	 **/
	renderToCanvas: function(canvas) {
		this._renderToCanvas(canvas);
		//this._bindEvents();
	},
	
	/**
	 * Interface for bind event after rendering
	 **/
	bindEvents: function(){
		this._bindEvents();
	},
	
	/**
	 * Remove my self from canvas
	 * @param - which canvas you want remove the object from
	 **/
	removeFromCanvas: function(canvas) {
		this._removeFromCanvas(canvas);
		this.unloadEvents();
	},
	
	/**
	 * This method defines how to scale shape during drag and drop mouse on canvas
	 * @param - x offset between start mouse x value and current mouse x value
	 * @param - y offset between start mouse y value and current mouse y value
	 **/
	scaleWithDrag: function(xOffset, yOffset) {
		this._scaleWithDrag(xOffset, yOffset);
	},
	
	/**
	 * Stop observing events
	 **/
	unloadEvents: function(){
	
	},
	
	/**
	 * Abstarct implementation of method bindEvents
	 **/
	_bindEvents: function(){
		
	},
	
	/**
	 * Abstarct implementation of method unloadEvents
	 **/
	_unloadEvents: function(){
	
	},
	
	/**
	 * Set attribute value by specific name. If the object doesn't have the attribute, create it and give it given value
	 * @param name - property name
	 * @param value - property value
	 **/
	setProperty: function(name, value){
		this._setProperty(name, value);
	},
	
	/**
	 * Get the center point of shape instance
	 * @return center point
	 **/
	getCenterPoint: function(){
		return this._getCenterPoint();
	},
	
	/**
	 * Get attribute value from object
	 * @param name - property name
	 * @return value of property
	 **/
	getProperty: function(name) {
		return this._getProperty(name);
	},
	
	/**
	 * Use this method to lock the location of object so it can not be moved.
	 **/
	lockMovement: function() {
		this._lockMovement();
	},
	
	/**
	 * Use this method to unlock the object so it can be moved
	 **/
	unlockMovement:function(){
		this._unlockMovement();
	},
	
	/**
	 * Call this method to display a shape on canvas
	 **/
	show: function(){
		this._show();
	},
	
	/**
	 * Call this method to hide a shape on canvas
	 **/
	hide: function(){
		this._hide();
	},
	
	/**
	 * Adjust down Z level
	 */
	sendBackwards: function(){
		this._sendBackwards();
	},
	
	/**
	 * Adjust up Z level
	 */
	bringForward: function(){
		this._bringForward();
	},
	
	
	/**
     * Add event lisenter for the instance
	 * @param event_name the name of observing event
	 * @param evecuter the this pointer for who call the method
	 * @param method event handler
     **/
    addObserver:function(event_name,executer,method){
	    var observer = new Observer(executer,method);
	    this.observerManager.AddObserver(event_name,observer);
    },
	  
    /**
     * Stop observe event
	 * @param event_name the name of observing event
	 * @param evecuter the this pointer for who call the method
	 * @param method event handler
     **/
    stopObserving:function(event_name,executer,method){
        var observer = new Observer(executer,method);
        this.observerManager.StopObserving(event_name,observer);
    },
  
    /**
     * Trigger event by giving event name
	 * @param event_name the name of observing event
	 * @param context context obect contains runtime variables
     **/
    notifyObserver:function(event_name,context){
        this.observerManager.NotifyAllObservers(event_name,context);
    },
	
	/**
	 * Get string of shape type
	 * @return shape type name
	 **/
	getShapeType: function(){
		return this._getShapeType();
	},
	
	/**
	 * Get fill color of shape
	 * @return shape color Hex value
	 **/
	getFillColor:function() {
		return this._getFillColor();
	},
	
	/**
	 * Get border color of shape
	 * @return shape color Hex value
	 **/
	getBorderColor:function() {
		return this._getBorderColor();
	},
	
	/**
	 * Get border width of shape
	 * @return shape width
	 **/
	getBorderWidth:function() {
		return this._getBorderWidth();
	},
	
	/**
	 * Get opacity of shape
	 * @return shape opacity
	 **/
	getOpacity:function() {
		return this._getOpacity();
	},
	
	/**
	 * Set fill color of shape
	 * @param color Hex string
	 **/
	setFillColor:function(color) {
		this._setFillColor(color);
	},
	
	/**
	 * Set border color of shape
	 * @param color Hex string
	 **/
	setBorderColor:function(color) {
		this._setBorderColor();
	},
	
	/**
	 * Set border width of shape
	 * @param width of shape border
	 **/
	setBorderWidth:function(width) {
	   this._setBorderWidth(width);
	},
	
	/**
	 * Set opacity of shape
	 * @param opacity shape opacity
	 **/
	setOpacity:function(opacity) {
	    this._setOpacity(opacity);
	},
	
	/**
	 * Returns visiablity of shape
	 * @return true if visble and false if hidden
	 **/
	isVisible: function() {
		return this._isVisible();
	},
	
	/**
	 * Bind shape to some event and specify the callback
	 * @param - options JSON
	 **/
	on: function(options) {
		this._on(options)
	},
	
	/**
	 * Get wrapped rectagnle
	 **/
	getBoundingRect: function() {
		return this._getBoundingRect();
	},
	
	/** 
	 * Clone current shape with new ID
	 **/
	clone: function(){
		return this._clone();
	}
}